package test.YTool;

import java.lang.reflect.Field;
import java.util.InputMismatchException;

// 复制两个对象
public class ObjectCopy {
	
	/**
	 * 一个一个地复制对象字段
	 * @param dest 要被复制的对象
	 * @param src  要被覆盖的对象
	 * @param clazz 两个对象要复制类型范围，不包括超类
	 */
	static void copySameTypeByField(Object dest, Object src, Class<?> clazz){
		if( null==src || null==dest ){
			throw new NullPointerException();
		}
		if( !clazz.isAssignableFrom(src.getClass()) || !clazz.isAssignableFrom(dest.getClass()) )
			throw new InputMismatchException();
		
		Field[] fields = clazz.getDeclaredFields();
		for(Field f: fields)
			try {
				f.set(dest, f.get(src));
			} catch (IllegalArgumentException e) {
				e.printStackTrace();
			} catch (IllegalAccessException e) {
				e.printStackTrace();
			}
	}
	
	/**
	 * 一个一个地复制对象字段
	 * @param dest 要被复制的对象
	 * @param src  要被覆盖的对象
	 * @param clazz 两个对象要复制类型范围，包括超类
	 */
	static void copySameTypeByFieldSuper(Object dest, Object src, Class<?> clazz){
		copySameTypeByField(dest, src, clazz);
		if( null!=clazz.getSuperclass() )
			copySameTypeByFieldSuper(dest, src, clazz.getSuperclass());
	}
	
	/**
	 * 一个一个地复制对象字段，只复制有相同名称的字段（两个对象可以不一样）
	 * @param dest 要被复制的对象
	 * @param src  要被覆盖的对象
	 */
	static void copyByField(Object dest, Object src){
		if( null==src || null==dest ){
			throw new NullPointerException();
		}
		
		Field[] fSrc = src.getClass().getDeclaredFields();
		Field[] fDest = dest.getClass().getDeclaredFields();
		for(Field s: fSrc)
		{
			for(Field d: fDest)
				if( s.getName().equals(d.getName()))	// 如果字段名相同
					copyFiled(s,d,src,dest);
		}
	}
	
	// 拷贝两个对象的同名字段
	private static void copyFiled(Field s, Field d, Object src, Object dest){
		try {
			Object os = s.get(src);
			Object od = d.get(dest);
			if( null==os ){			// 如果 src 字段 为 null
				if( null==od );		// 都是 null 什么不用做
				else {
					boolean isBaseClass = AssignBasicClassNull(d,dest);
					if( !isBaseClass ){
						//d.set(dest, null);	这样会异常
						//od = null;	// 貌似 od 是个副本,不影响真正的对象
						d.set(dest, od.getClass().getConstructor().newInstance());
					}
						
				}
			}else{
				try {
					d.set(dest,s.get(src));	// 只要名字相同的字段强行赋值,不行直接忽略异常
				} catch (Exception e){
					System.out.println();
				}
			}
		} catch (Exception e1) {
			e1.printStackTrace();
		}
	}
	
	// 基础类型直接赋给默认值
	private static boolean AssignBasicClassNull(Field d, Object dest) 
			throws IllegalArgumentException, IllegalAccessException{
		Class<?> clazz = d.get(dest).getClass();

		if( int.class==clazz || long.class==clazz || short.class==clazz ){
			d.set(dest,0);
			return true;
		}
		else if( boolean.class==clazz ){
			d.set(dest,false);
			return true;
		}
		else if( char.class==clazz){
			d.set(dest,0);
			return true;
		}
		else if( double.class==clazz || float.class==clazz ){
			d.set(dest,0.0);
			return true;
		}
		
		return false;
	}
	
	// 遍历基本类型来赋值
	private static void assignBaseValue(Field s, Field d, Object src, Object dest){
		try {
			Class<?> destClass = d.get(dest).getClass();
			Class<?> srcClass = s.get(src).getClass();
			if( int.class==destClass || Integer.class==destClass ){
				if( int.class==srcClass || Integer.class==srcClass )
					d.set(dest, s.getInt(src));
			}
//			else if( String.class==destClass ){
//				if( String.class==srcClass )
//					//d.set(dest, src.toString());
//					d.set(dest,s.get(src));
//			}
			else if( long.class==destClass || Long.class==destClass ){
				if( long.class==srcClass || Long.class==srcClass )
					//d.set(dest, s.getLong(src));
					d.set(dest,s.get(src));
			}
			else if( short.class==destClass || Short.class==destClass ){
				if( short.class==srcClass || Short.class==srcClass )
					//d.set(dest, s.getShort(src));
					d.set(dest,s.get(src));
			}
			else if( boolean.class==destClass || Boolean.class==destClass ){
				if( boolean.class==srcClass || Boolean.class==srcClass )
					//d.set(dest, s.getBoolean(src));
					d.set(dest,s.get(src));
			}
			else if( char.class==destClass || Character.class==destClass ){
				if( char.class==srcClass || Character.class==srcClass )
					//d.set(dest, s.getChar(src));
					d.set(dest,s.get(src));
			}
			else if( byte.class==destClass || Byte.class==destClass ){
				if( byte.class==srcClass || Byte.class==srcClass )
					//d.set(dest, s.getByte(src));
					d.set(dest,s.get(src));
			}
			else if( double.class==destClass || Double.class==destClass ){
				if( double.class==srcClass || Double.class==srcClass )
					//d.set(dest, s.getDouble(src));
					d.set(dest,s.get(src));
			}
			else if( float.class==destClass || Float.class==destClass ){
				if( float.class==srcClass || Float.class==srcClass )
					//d.set(dest, s.getFloat(src));
					d.set(dest,s.get(src));
			}
			//else
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}
